﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using Xceed.Silverlight.Compatibility;

namespace Xceed.Silverlight.DataGrid
{
  public class ColumnElementsHost : Panel
  {
    public ColumnElementsHost()
    {
      DataGridBehaviors.SetClipElement( this, true );
      this.Children.Add( m_leftFixedPanel );
      this.Children.Add( m_rightFixedPanel );
      this.Children.Add( m_scrollablePanel );
    }

    internal IEnumerable<ColumnElementWrapper> Elements
    {
      get
      {
        return this.UIElements.Cast<ColumnElementWrapper>();
      }
    }

    public double CellsIndent
    {
      get
      {
        return m_leftFixedPanel.CellsIndent;
      }
      set
      {
        m_leftFixedPanel.CellsIndent = value;
      }
    }

    private IEnumerable<UIElement> UIElements
    {
      get
      {
        return CompatibilityUtils.GetEnumerable(m_scrollablePanel.Children)
          .Concat(CompatibilityUtils.GetEnumerable(m_leftFixedPanel.Children))
          .Concat(CompatibilityUtils.GetEnumerable(m_rightFixedPanel.Children));
      }
    }

    internal void TransfertCells( ColumnElementsHost cellsHost )
    {
      cellsHost.CellsIndent = this.CellsIndent;
      this.TransferCells( m_leftFixedPanel, cellsHost.m_leftFixedPanel );
      this.TransferCells( m_rightFixedPanel, cellsHost.m_rightFixedPanel );
      this.TransferCells( m_scrollablePanel, cellsHost.m_scrollablePanel );
    }

    private void TransferCells( ColumnElementsInnerHost fromPanel, ColumnElementsInnerHost toPanel )
    {
      IList<UIElement> cells = CompatibilityUtils.GetEnumerable( fromPanel.Children ).ToList();

      fromPanel.Children.Clear();
      foreach( UIElement cell in cells )
      {
        toPanel.Children.Add( cell );
      }
    }

    internal void AddColumnElement( ColumnElementWrapper element )
    {
      ColumnPosition position = element.ColumnElement.ParentColumnContainer.ColumnPosition;
      if( position == ColumnPosition.Scrollable )
      {
        m_scrollablePanel.Children.Add( element );
      }
      else if( position == ColumnPosition.LeftFixed )
      {
        m_leftFixedPanel.Children.Add( element );
      }
      else
      {
        Debug.Assert( position == ColumnPosition.RightFixed );
        m_rightFixedPanel.Children.Add( element );
      }
    }

    internal void RemoveColumnElement( ColumnElementWrapper element )
    {
      if( !CompatibilityUtils.RemoveElement( m_scrollablePanel.Children, element ) )
      {
        if( !CompatibilityUtils.RemoveElement( m_leftFixedPanel.Children, element ) )
        {
          bool removed = CompatibilityUtils.RemoveElement( m_rightFixedPanel.Children, element );
          Debug.Assert( removed );
        }
      }
    }

    internal void SetElementPosition( ColumnElementWrapper element, ColumnPosition position )
    {
      if( position == ColumnPosition.Scrollable )
      {
        this.SetElementPanel( element, m_scrollablePanel, m_leftFixedPanel, m_rightFixedPanel );

      }
      else if( position == ColumnPosition.LeftFixed )
      {
        this.SetElementPanel( element, m_leftFixedPanel, m_scrollablePanel, m_rightFixedPanel );
      }
      else 
      {
        Debug.Assert( position == ColumnPosition.RightFixed );
        this.SetElementPanel( element, m_rightFixedPanel, m_scrollablePanel, m_leftFixedPanel );
      }
    }

    private void SetElementPanel( ColumnElementWrapper element, ColumnElementsInnerHost targetPanel, ColumnElementsInnerHost otherPanel1, ColumnElementsInnerHost otherPanel2 )
    {
      ColumnElementsInnerHost sourcePanel = null;

      if( CompatibilityUtils.RemoveElement( otherPanel1.Children, element ) )
      {
        sourcePanel = otherPanel1;
      }
      else if( CompatibilityUtils.RemoveElement( otherPanel2.Children, element ) )
      {
        sourcePanel = otherPanel2;
      }

      if( sourcePanel != null )
      {
        targetPanel.Children.Add( element );
      }
    }

    protected override Size MeasureOverride( Size availableSize )
    {
      m_leftFixedPanel.Measure( availableSize );
      m_rightFixedPanel.Measure( availableSize );
      m_scrollablePanel.Measure( availableSize );


      Size leftSize = m_leftFixedPanel.DesiredSize;
      Size rightSize = m_rightFixedPanel.DesiredSize;
      Size scrollSize = m_scrollablePanel.DesiredSize;

      double height = Math.Max(leftSize.Height, rightSize.Height);
      height = Math.Max(height, scrollSize.Height);
      return new Size( 0, height );
    }


    protected override Size ArrangeOverride( Size finalSize )
    {
      Size leftSize = m_leftFixedPanel.DesiredSize;
      Size rightSize = m_rightFixedPanel.DesiredSize;
      Size scrollSize = m_scrollablePanel.DesiredSize;
      double remainingWidth = finalSize.Width;

      double leftWidth = Math.Min( remainingWidth, leftSize.Width );
      remainingWidth = Math.Max(0d, remainingWidth - leftWidth);

      double rightWidth = Math.Min( remainingWidth, rightSize.Width );
      remainingWidth = Math.Max( 0d, remainingWidth - rightWidth );

      double scrollWidth = Math.Min( remainingWidth, scrollSize.Width );

      m_leftFixedPanel.Arrange( new Rect( 0, 0, leftWidth, finalSize.Height ) );
      m_rightFixedPanel.Arrange( new Rect( finalSize.Width - rightWidth, 0, rightWidth, finalSize.Height ) );
      m_scrollablePanel.Arrange( new Rect( leftWidth, 0, scrollWidth, finalSize.Height ) );

      return finalSize;
    }

    internal void InvalidateColumnArrange()
    {
      this.InvalidateArrange();
      m_leftFixedPanel.InvalidateArrange();
      m_rightFixedPanel.InvalidateArrange();
      m_scrollablePanel.InvalidateArrange();
    }

    internal void InvalidateColumnMeasure()
    {
      this.InvalidateMeasure();
      m_leftFixedPanel.InvalidateMeasure();
      m_rightFixedPanel.InvalidateMeasure();
      m_scrollablePanel.InvalidateMeasure();
    }

    private ColumnElementsInnerHost m_leftFixedPanel = new ColumnElementsInnerHost();
    private ColumnElementsInnerHost m_rightFixedPanel = new ColumnElementsInnerHost();
    private ColumnElementsInnerHost m_scrollablePanel = new ColumnElementsInnerHost();
  }
}
